/*
 * Created on 11-Nov-2004
 *
 * By Mike Anderson
 */
package game.jrogue;

import java.util.Date;

/**
 * @author Mike
 *
 * This class implements a small tutorial area for beginners
 * 
 * 
 */
public class Tutorial {
    private static class RoscoBurrl extends Script
    {
        public RoscoBurrl() {
            chattedToHero = false;
        }
        private static final long serialVersionUID = 3258417222518321461L;
        private boolean chattedToHero;
        private MiiraTheRanger miira;

        public final boolean isChattedToHero() {
            return chattedToHero;
        }
        /** The method is supposed to be called only once - just when
         *  MiiraTheRanger object is available.
         *  We need to know MiiraTheRanger object to request
         *  MiiraTheRanger.isChattedToHero().
         */
        public void setMiira(final MiiraTheRanger miira) {
            this.miira = miira;
        }

        /** The method PROBABLY says hello
         */
        private void tryToSayHello(final Thing h) {
            Tutorial.sayHello(h, 0.3, 0.1, 0.1);
        }
        public boolean handle(Thing t, Event e) {
            chattedToHero = true;
            final Thing h = e.getThing("Target");
            t.incStat("대화횟수",1);
            switch (t.getStat("대화횟수")) {
                case 1:
                    sayName(t);
                    tryToSayHello(h);
                    Game.message("그는 열심히 침 튀겨가며 무시무시한 " +
                            Text.krSub(Lib.createType("IsMonster",RPG.d(16)).getName(Game.hero()), "와") +
                            "의 전투에서 자신이 어떻게 이겼는지를 자랑합니다..");
                    break;

                case 2:
                    sayName(t);
                    Game.quotedMessage("알고 있나? 쌈을 잘 하는건 거기 곧바로 뛰어드는게 아냐. 뒤로 물러서서 그녀석이 다가오길 기다린 뒤, 그 녀석이 눈치채기 전에 그대로 엉덩이를 걷어차 주는 거지!");
                    break;

                case 3:
                    sayName(t);
                    Game.quotedMessage("절대로 적들에게 둘러싸이는 누를 범하지 말게! 좁은 길을 가로막고 있으면 한놈씩 한놈씩 처리할수 있을 거야. 내가 항상 그렇게 싸우지.");
                    break;

                case 4:
                    sayName(t);
                    if (RPG.p(0.5)) {
                        Game.quotedMessage("보록이라는 사악한 고블린이 있네. "
                        		+"작년에 몇몇 마을사람들을 죽였지. 깊은 숲 속 유적 지하에 자기 소굴을 마련했다더군. "
                        		+"북쪽으로 갈 생각인가? 그런 악당을 물리칠 수 있는 영웅은 금방 유명해질걸세!");
                    } else
                    {
                        Game.quotedMessage("이봐 친구, 조언을 하나 해 주지. 싸울땐 오른손에 무기를 들고 왼손에 방패를 드는게 제일 낫다네. 알겠나?");
                    }
                    break;

                case 5:
                    sayName(t);
                    if (RPG.p(0.5) && miira != null && !miira.isChattedToHero()) {
                        Game.quotedMessage("방 저쪽에 있는 순찰자 미라와 대화를 나눠 봤나? 한번 이야기해 보게나.");
                    } else {
                        Game.quotedMessage("알고있나? 중요한 건 자네가 불리할 때 계속 싸우지 않는걸세. 다음날 해 뜨는걸 볼 수 있을때만 싸우게나!");
                    }
                    break;

                default:
                    Game.message(Text.krSub(t.getTheName(), "이") + " 당신과 잠깐 이야기를 나눕니다.");
                    t.set("대화횟수", 100);
                    break;
            }
            return false;
        }
    }//class RoscoBurrl

    private static class SilasInnkeeper extends Script
    {
			public SilasInnkeeper()
            {
                chattedToHero = false;
            }
            private static final long serialVersionUID = 3258939205411305016L;
            /* Date of last conversation
             */
            private Date lastTime = null;
            /* TIME_MIN and TIME_MAX contain time (in milliseconds). They create
             * range [TIME_MIN, TIME_MAX] to select time randomly from it.
             */
            private final static int TIME_MIN = 5*60*1000;
            private final static int TIME_MAX = 6*60*1000;
            private Thing t;
            private boolean chattedToHero;
            private MiiraTheRanger miira;

            /** The method is supposed to be called only once - just when
             *  MiiraTheRanger object is available.
             *  We need to know MiiraTheRanger object to request
             *  MiiraTheRanger.isChattedToHero().
             */
            public void setMiira(final MiiraTheRanger miira) {
                this.miira = miira;
            }
            public final boolean isChattedToHero() {
                return chattedToHero;
            }
            private boolean isLongTime() {
                if (lastTime == null)
                    return false;
                final long diff = (new Date()).getTime() - lastTime.getTime();
                final long threshold = RPG.r(TIME_MIN, TIME_MAX);
                return diff > threshold;
            }

            private void sayYouAgain() {
                final String arr[] = {
                    "아아, 또 자네로군. 여행자 씨.",
                    "아, 자네 또왔나. 방문자.",
                    "당신 또 왔군, 여행자분.",
                    "다시 만나서 반갑군, 여행자 씨.",
                    "다시 살아서 보게 되니 기쁘군, 방문자.",
                    "다시 왔나, 여행자분."
                };
                Game.quotedMessage(RPG.pick(arr));
            }

            private void sayHello() {
                /*-----
                 Some races we regard as "exotic". For them we can say hello like
                 "Oh, you are hawken...we never saw them here. Welcome to my Inn!"

                 In some cases we can use race name in greeting: "Hi, gnome, welcome "
                 to my Inn!"

                 And, eventually, greeting can be simple: "Welcome to my inn!"
                 -----*/
                sayName(t);
                final String race = Game.hero().getString("종족");
                if (isExoticRace(race)) {
                    if (RPG.p(0.3)) {
                        sayHelloNeverSawYouHere(race);
                        return;
                    }
                    if (RPG.p(0.2)) {
                        sayHelloUsingRace(race);
                        return;
                    }
                }
                final String[] hello = {
                    "내 여관에 어서오시게!",
                    "내 여관에선 여행자들을 언제나 환영하지!",
                    "어서오시게, 손님!",
                    "안녕하신가, 손님!",
                    "좋은날이군, 손님!",
                    "안녕하신가, 여행자!",
                    "내 여관에 어서오시게, 여행자!",
                    "내 여관에 어서오시게, 손님!",
                    "어서오시게나!",
                    "내 여관에 오신걸 환영하네!",
                    "자네같은 여행자를 만나게 된 게 기쁘구만!",
                    "자, 손님. 어서 들어오시게!",
                    "자, 여행자분. 어서 들어오시게!"
                };
                Game.quotedMessage(RPG.pick(hello));
            }

            private void sayHelloNeverSawYouHere(final String race) {
                final String part1 = "오, 자네는 ";
                final String part2 = "로군....여기선 보기 힘든 부류인데.";
                final String[] part3 = {
                    " 아무튼 내 여관에 어서오시게!",
                    " 아무튼 내 여관에 오신걸 환영하네!",
                    " 아무튼 내 여관에 와서 반갑구먼!"
                };
                String s = part1 + Text.krSub(race,"이름") + part2 + RPG.pick(part3);
                Game.quotedMessage(s);
            }

            private void sayHelloUsingRace(final String race) {
                final String[] start = {
                    "Welcome to my inn, ",
                    "Hi, ",
                    "Hello, ",
                    "Nice to see you in my inn, ",
                    "Hello, nice to see you in my inn, "
                };
                Game.quotedMessage(RPG.pick(start) + race +  "!");
            }

            private void sayAboutMiira() {
                if (miira != null && miira.isChattedToHero()) {
                    Game.quotedMessage("I see you've already talked to Miira the " +
                        "ranger in this room. Cool girl, isn't she?");
                    return;
                }
                Game.quotedMessage("There is Miira the ranger in this room. " +
                    "Talk to her: she can say something interesting.");
            }

            public boolean handle(Thing t, Event e) {
                chattedToHero = true;
                this.t = t;
                Thing h=e.getThing("Target");
                t.incStat("대화횟수",1);
				switch (t.getStat("대화횟수")) {
					case 1:
                        {
                        sayHello();
                		break;
                        }

					case 2:
                        {
                        if (Tutorial.isBusy(0.1, h.getStat("CH"), 6)) {
                            t.set("대화횟수", 2);
                            break;
                        }
						sayName(t);
                        if (isLongTime()) {
                            sayYouAgain();
                            break;
                        }
                        final String[] arr1 = {
                            "If you're after a job to do, there are some pests down in the cellar that need clearing out.",
                            "Are you after a job to do? There are some pests down in the cellar that need clearing out.",
                            "Are you after a job to do? Some pests down in the cellar need clearing out.",
                            "You know, there are some pests down in the cellar that need clearing out.",
                            "You know, some pests down in the cellar need clearing out.",
                            "Listen, there are some pests down in the cellar that need clearing out.",
                             "You know what? Some pests down in the cellar need clearing out."};
                        final String[] arr2 = {
                            " You can help yourself to the funny old potions down there,",
                            " You may be interested in the funny old potions down there,"
                        };
                        final String[] arr3 = {
                            " I know you adventurers can always find a use for them.",
                            " you adventurers can always find a use for them.",
                            " adventurers like you can always find a use for them.",
                            " travelers like you can always find a use for them."
                        };
                        Game.quotedMessage(RPG.pick(arr1) + RPG.pick(arr2) +
                                RPG.pick(arr3));
						break;
                        }

					default:
                        {
                        sayName(t);
                        if (isLongTime())
                        {
                            sayYouAgain();
                            final String[] arr = {
                                "지하실에서 뭔가 찾았길 바라네.",
                                "그 지하실에서 뭔가 찾았길 바라네.",
                                "에또, 지하실에서 뭔가 찾았나?",
                                "지하실에서 쓸만한 걸 좀 찾았나?",
                                "이미 지하실에 가 봤길 바라네.",
                                "자네에게 말했던 지하실에 이미 가 보았길 바라네."
                            };
                            Game.quotedMessage(RPG.pick(arr));
                        }
                        else
                        {
                            if (RPG.test(h.getStat("CH"), 3) && RPG.p(0.5)) {
                                sayAboutMiira();
                            }
                            else
                            {
                                final String[] arr1 = {
                                    "The cellar I told you about is to the south from this room.",
                                    "That cellar I told you about is to the south from this room.",
                                    "By the way, the cellar I told you about is to the south from this room.",
                                    "I told you about a cellar; you can find it to he south from this room.",
                                    "I told you about a cellar; it is located to he south from this room."
                                };
                                final String[] arr2 = {
                                    "",
                                    " 몸 조심하시게!",
                                    " 몸 조심하시게, 몬스터나 다른 무서운 것들이 거기 있을지 모르니.",
                                    " 몸 조심하시게, 자네도 알다시피, 어두운데다, 몬스터라든지, 같은것들 말일세.",
                                    " 몸 조심하시게, 몬스터가 나올수도 있으니 말이야.",
                                    " 몬스터가 그 안에 있을수도 있네, 그러니 몸조심하게!"
                                };
                                Game.quotedMessage(RPG.pick(arr1) +
                                        RPG.pick(arr2));
                            }
                        }
						t.set("대화횟수", 100);
						break;
                        }
				}
                this.t = null;
                lastTime = new Date();
				return false;
			}
    }

    private static class MiiraTheRanger extends Script
    {
        public MiiraTheRanger()
        {
            chattedToHero = false;
        }

        private SilasInnkeeper silasInnkeeper;
        private RoscoBurrl rosco;
        private boolean chattedToHero;

        private static final long serialVersionUID = 4049633512149890352L;

        /* Date of last conversation
         */
        private Date lastTime = null;
        /* TIME_MIN and TIME_MAX contain time (in milliseconds). They create
         * range [TIME_MIN, TIME_MAX] to select time randomly from it.
         */
        private final static int TIME_MIN = 1*60*1000;
        private final static int TIME_MAX = 2*60*1000;


        public final boolean isChattedToHero() {
            return chattedToHero;
        }
        /** The method is supposed to be called only once - just when
         *  RoscoBurrl object is available.
         *  We need to know RoscoBurrl object to request
         *  RoscoBurrl.isChattedToHero().
         */
        public void setRosco(final RoscoBurrl rosco) {
            this.rosco = rosco;
        }
        /** The method is supposed to be called only once - just when
         *  SilasInnkeeper object is available.
         *  We need to know SilasInnkeeper object to request
         *  SilasInnkeeper.isChattedToHero().
         */
        public void setSilas(final SilasInnkeeper silasInnkeeper) {
            this.silasInnkeeper = silasInnkeeper;
        }

        private boolean isLongTime() {
            if (lastTime == null)
                return false;
            final long diff = (new Date()).getTime() - lastTime.getTime();
            final long threshold = RPG.r(TIME_MIN, TIME_MAX);
            return diff > threshold;
        }

        /** The method PROBABLY says hello
         */
        private void tryToSayHello(final Thing h) {
            Tutorial.sayHello(h, 0.5, 0.3, 0.3);
        }

        private void sayAboutSilasInnkeeper() {
            final String[] word = {
                "수전노",
                "구두쇠"
            };
            if (silasInnkeeper != null && silasInnkeeper.isChattedToHero()) {
                Game.quotedMessage("아, 자네 이미 이 방 내의 여관주인 실라스와 이야기를 했군 그래. " +
                    "그는 그냥 살찐 " + RPG.pick(word) + "일 뿐이지, 안그런가?");
                return;
            }
            Game.quotedMessage("왼쪽에 여관주인 실라스가 보이나? 그는  " +
                    RPG.pick(word) +
                    "일세. 아무것도 공짜로 내주진 않을게야.");
        }

        private void sayFinalPhrase() {
            if (RPG.p(0.8) && rosco != null && !rosco.isChattedToHero()) {
                Game.quotedMessage("이 방 안의 로스코 버얼이 보이나? 그와 한번 이야기를 나눠보게.");
                return;
            }
            sayIamBored();
        }

        private void sayIamBored() {
            final String[] bored = {
                "자네랑 이야기하기 좀 지루하군.",
                "미안해, 자네랑 이야기하기 좀 지루하네.",
                "미안, 자네랑 이야기하는건 좀 지루한데.",
                "미안해 친구, 자네랑 더이상 이야기할만한게 없어.",
                "미안한데 자네랑 이야기할 거리가 더 없네.",
                "미안한데 더이상 자네에게 해 줄 이야기가 없어, 친구.",
                "미안한데 자네와 나눌 이야기거리가 더이상 없네.",
                "더이상 자네에게 해줄 말이 없네, 미안해."
            };
            Game.quotedMessage(RPG.pick(bored));
        }

        public boolean handle(Thing t, Event e) {
            chattedToHero = true;
            Thing h=e.getThing("Target");
            t.incStat("대화횟수",1);
            switch (t.getStat("대화횟수")) {
                case 1:
                    sayName(t);
                    tryToSayHello(h);
                    Game.message("당신은 몇가지 여행자들간의 농담을 나눕니다.");
                    break;
                case 2:
                    sayName(t);
                    if (Tutorial.isBusy(0.1, h.getStat("CH"), 6)) {
                        t.set("대화횟수", 2);
                        break;
                    }
                    if (RPG.test(h.getStat("CH"), 20)) {
                        Item.identify(Lib.create("칸꽃"));
                        Game.message(Text.krSub(t.getTheName(), "은") +
                                " 당신에게 장갑을 끼지 않고 칸꽃을 꺾지 말라고 경고해줍니다.");
                    }
                    else
                    {
                        sayAboutSilasInnkeeper();
                    }
                    break;
                case 3:
                    if (RPG.test(h.getStat("CH"), 3)) {
                        //-Let's give an advice to Hero
                        sayName(t);
                        if (RPG.p(0.5)) {
                            Game.quotedMessage("기억하게: " +
                                    "산을 넘으려면 등반 기술을 알고 있어야 한다네.");
                        } else {
                            Game.quotedMessage("여기 북쪽에 있는 작은 성소를 아직 방문하지 않았나?");
                        }
                        break;
                    }
                    Game.message("당신은 잠깐동안 담소를 나눕니다.");
                    if (!RPG.test(h.getStat("CH"),3)) {
                        Game.message(Text.krSub(t.getTheName(), "이")+ " 하품을 합니다.");
                        t.set("대화횟수",100);
                    }
                    break;
                case 4:
                    Game.message("You talk about how best to defeat " +
                            Lib.createType("IsMonster",RPG.d(16)).getAName() +
                            ".");
                    if (RPG.test(h.getStat("CH"), 13)) {
                        Game.message(t.getTheName()+" seems impressed with your insight.");
                        Game.message("She gives you an identify scroll.");
                        Game.quotedMessage("Read this if you need to figure out what a mysterious item does.");
                        Thing it=Lib.create("scroll of Identify");
                        Item.identify(it);
                        h.addThing(it);
                    }
                    break;

                default:
                    sayName(t);
                    if (isLongTime()) {
                        Game.quotedMessage("아아, 또 자네로군. 무슨일인가?");
                    }
                    else {
                        sayFinalPhrase();
                    }
                    t.set("대화횟수",100);
                    break;

            }
            lastTime = new Date();
            return false;
        }
    }

    private static class BurthaTheTownsWoman extends Script
    {
        static final long serialVersionUID = -3409510129139664108L;

        public boolean handle(Thing t, Event e) {
            t.incStat("대화횟수",1);
            switch (t.getStat("대화횟수")) {
                case 1:
                    {
                        final String firstPhrase[] = {
                            "난 마을 아낙네일세. 뭘 원하나?",
                            "난 그냥 마을 아낙네일세...뭘 원하는겐가?",
                            "What is you wantin'?",
                            "What is you wantin', pal?",
                            "Whatchoo want, pal?",
                            "What?",
                            "Wassup?",
                            "Wassup, pal?",
                            "Hey, wassup?",
                            "What?",
                            "Wanna somethin'?",
                            "U wanna somethin'?",
                            "Wanna somethin', ah?",
                            "Wanna somethin', pal?"};
                        sayName(t);
                        Game.quotedMessage(RPG.pick(firstPhrase));
                    }
                    break;
                case 2:
                    sayName(t);
                    Game.quotedMessage("저기 저 햄이 보이나? 저건 내 꺼 라 구!");
                    break;
                default:
                    {
                        sayName(t);
                        final String finalPhrase[] = {
                            "말했잖나, 이 햄은 내꺼야! 이 햄 조각은 내꺼라구! 한번만 더 이걸 훔쳐가려 하면 가만두지 않을테다!",
                            "말했잖나, 이 힘은 내꺼야! 내가 네게 이 걸 넘겨주리라고 상상도 하지 마!"
                        };
                        Game.quotedMessage(RPG.pick(finalPhrase));
                        t.set("대화횟수",100);
                        break;
                    }
            }//switch
            return false;
        }
    }

    private static class RotchyTheFarmer extends Script
    {
        private static final long serialVersionUID = 6595782575469702238L;

        public boolean handle(Thing t, Event e) {
            t.incStat("대화횟수",1);
            switch (t.getStat("대화횟수")) {
                case 1:
                    sayName(t);
                    Game.quotedMessage("Hello, Sir. I'm just a farmer. Can I help you?");
                    break;
                case 2:
                    sayName(t);
                    Game.quotedMessage("There is nice inn to the north. Visit it if you haven't been there yet.");
                    break;
                case 3:
                    sayName(t);
                    Game.quotedMessage("You see stairs down nearby? This is entrance to cellar; but I did not ever dare to go down there.");
                    break;
                default:
                    sayName(t);
                    if (RPG.p(0.5))
                    {
                        Game.quotedMessage("I could just add: beware of monsters!");
                    }
                    else
                    {
                        Game.quotedMessage("I'm afraid, Sir, there is nothing more I can tell you.");
                    }
                    t.set("대화횟수",100);
                    break;
            }//switch
            return false;
        }
    }

	public static Map buildLoft() {
		Map m=new Map(5,9);
		m.setTheme("동굴");
		m.set("레벨",1);
		m.set("설명","작은 다락방");
		
		// first room
		m.fillArea(1,1,3,3,m.floor());
		m.setEntrance(Lib.create("내려가는 사다리"));
		m.addThing(m.getEntrance(),1,1);
		
		// second room
		m.setTile(2,4,m.floor());
		Thing door=Lib.create("trapped black door");
		door.set("KeyName","여관 다락층 열쇠");
		m.addThing(door,2,4);
        m.addThing(
            Special.messagePoint("남쪽의 문을 열려면 열쇠가 필요합니다.")
            ,2,3);

		m.fillArea(1,5,3,7,m.floor());
		
		m.addThing(
				Special.messagePoint("당신의 남쪽에 상자가 놓여 있습니다. 당신은 그 위로 올라가 상자열기를 시도할 수 있습니다. 상자는 때때로 잠겨 있을 수도 있습니다. 이 경우 당신은 그것을 억지로 열거나 다른 방법을 사용해 상자의 자물쇠를 풀어야 할 것입니다. 만약 당신이 상자를 여는데 성공한다면, \",\" 키를 눌러 그 안에 있던 아이템을 가질 수 있습니다.")
				,2,6
		);
		m.addThing(Lib.create("[IsChest]"),2,7);
		
		m.replaceTiles(0,m.wall());
		return m;
	}

	
	public static Map buildCellar() {
		Map m=new Map(25,25);
		m.setTheme("동굴");
		m.set("레벨",1);
		m.set("설명","어두운 지하실");
		
		// initial room
		m.setEntrance(Lib.create("올라가는 계단"));
		m.fillArea(1,1,5,5,Tile.CAVEFLOOR);
		m.addThing(m.getEntrance(),2,2);
		
		Thing h=Game.hero();
		
		if (h.getFlag(Skill.LITERACY)) {
			m.addThing(Scroll.note("노트","로치 - 이 곳엔 너무 쥐가 많아. 너무 위험할거야. 만약 마을에 간다면 독약을 좀 찾아와야겠어."),3,3);
			m.addThing(
					Special.messagePoint("바닥에 노트가 떨어져 있습니다. \",\"키로 이 노트를 집을 수 있습니다. 당신이 읽기 기술을 가지고 있다면 \"r\" 키를 눌러 그것을 읽을 수 있습니다.")
					,3,3
			);
		}
		
		// the maze
		Maze.buildMaze(m,6,0,12,12);
		m.setTile(6,3,Tile.CAVEFLOOR);
		m.addThing(Lib.create("쇠창살"),6,3);
		m.addThing(
				Special.messagePoint("이 구부러진 통로는 거의 미궁과도 같은 이상한 형태로 만들어져 있습니다. 아마도 이 지하실은 이전에 고대 지하 동굴이었던 것 같습니다.")
				,6,3
		);
		
		// rat room
		m.fillArea(1,7,5,11,m.floor());
		m.setTile(6,11,m.floor());
		m.addThing(Lib.create("문"),6,11);
		m.addThing(
				Special.messagePoint("당신은 이 문 저편에서 쥐들의 찍찍거리는 소리를 들을 수 있습니다. 정말로 싸울 준비가 되셨습니까? 전투를 준비하시려면 \"w\" 키를 눌러 무기를 장비하거나 보호구를 입도록 하세요. 적을 공격하시려면 커서 키를 이용해서 그 적에게 돌진하시면 됩니다.")
				,7,11
		);
		for (int i=0; i<6; i++) {
			m.addThing(Lib.create("[IsRat]"),1,7,5,11);
		}
		m.addThing(
				Special.messagePoint("때때로 지하동굴 내에는 감춰진 지역이 있습니다. \"s\"를 누르면 자기 주변 영역을 조사할 수 있습니다.")
				,1,11
		);
		m.addThing(Lib.create("숨겨진 문"),1,12);
		m.addThing(
				Special.messagePoint("여기에 물약이 놓여 있습니다. 물약은 종종 당신의 모험에 커다란 도움을 줄 수 있는 마법적 효능을 지니고 있습니다. 그러나 그 중에는 나쁜 효과를 지닌것들도 있기에 효과가 밝혀지지 않은 물약을 아무거나 들이키는 것은 위험할 수 있습니다. 당신은 \"q\" 키를 눌러 물약을 마실 수 있습니다.")
				,1,7
		);
		m.addThing(Lib.create("[IsPotion]"),1,7);

		
		// secret room
		m.fillArea(1,13,5,17,m.floor());
		m.addThing(Lib.create("rat cave"),2,17);
		m.addThing(Lib.create("[IsFood]"),3,14);
		m.addThing(
				Special.messagePoint("If you become hungry during your adventures, you will need to find food. The item here can be eaten by picking it up and pressing \"e\"")
				,3,14
		);
		m.addThing(Lib.create("[IsPotion]"),4,14);
		m.addThing(Lib.create("[IsSnake]"),3,14);
		m.addThing(
				Special.messagePoint("This small tunnel is too tight for you to enter. However, you could easily be surprised by rats coming out of it. Be careful!")
				,2,17
		);
		
		// big room
		m.setTile(6,15,m.floor());
		m.addThing(Lib.create("쇠창살"),6,15);
		m.fillArea(7,13,12,23,m.floor());
		for (int y=14; y<=22; y+=2) {
			m.setTile(8,y,m.wall());
			m.setTile(11,y,m.wall());
		}
		m.addThing("뼈",9,15);
		m.addThing(
				Special.messagePoint("Many items in jRogue have multiple uses. A bone for example, can be wielded as a weapon by pressing \"w\". Alternatively, if you are feeling hungry you can eat it by pressing \"e\".")
				,9,15
		);
		
		// back room
		m.setTile(6,21,m.floor());
		m.addThing(Lib.create("썩어가는 문"),6,21);
		m.fillArea(1,19,5,23,m.floor());
		m.addThing(Lib.create("코볼드"),3,21);
		{
			Thing key=Lib.create("여관 다락층 열쇠");
			m.addThing(key,3,21);
		}
		
		// viewing room
		m.fillArea(13,1,23,3,m.floor());
		m.setTile(12,3,m.floor());
		m.addThing("문",12,3);
		Thing mon=Lib.createType("IsMonster",2);
		m.addThing(
				Special.messagePoint("You hear something moving behind this door. Sounds like "+mon.getAName()+"! If you open the door, be ready to fight. Wield your weapons and wear armour by pressing \"w\". In close combat, you can attack by simply running into the monster.")
				,11,3
		);
		m.addThing(mon,15,3);
		m.addThing(
				Special.messagePoint("This portcullis (to the south of you) can never be opened. It may be useful though, since you can always get a clear view of the room on the other side! Press \"l\" to look at a distant object.")
				,14,3
		);
		
		for (int x=14; x<=22; x+=4) {
			m.setTile(x,4,m.floor());
			m.addThing("파괴불가능한 쇠창살",x,4);
			m.fillArea(x-1,5,x+1,7,m.floor());
			String th=RPG.pick(new String[] {"[IsChest]","[IsStoreItem]","[IsMonster]","불뱀"});
		    m.addThing(th,x,6);	
		    if (th.equals("[IsChest]")) {
				m.addThing(
					Special.messagePoint("당신의 북쪽에 상자가 놓여 있습니다. 당신은 그 위로 올라가 상자열기를 시도할 수 있습니다. 상자는 때때로 잠겨 있을 수도 있습니다. 이 경우 당신은 그것을 억지로 열거나 다른 방법을 사용해 상자의 자물쇠를 풀어야 할 것입니다. 만약 당신이 상자를 여는데 성공한다면, \",\" 키를 눌러 그 안에 있던 아이템을 가질 수 있습니다.")
						,x,7
				);
		    }
		   
			m.setTile(x,8,m.floor());
			m.addThing("문",x,8);
		}
		m.fillArea(13,9,23,10,m.floor());
		
		// tunnels
		m.makeRandomPath(13,21,18,12,14,12,21,23,m.floor(),false);
		m.makeRandomPath(18,12,21,23,14,12,21,23,m.floor(),false);
		m.setTile(14,21,m.floor());
		m.setTile(23,23,m.floor());
		m.addThing("[IsTrap]",23,23);
		m.addThing("[IsStoreItem]",23,23);
		m.setTile(22,23,m.floor());
		m.addThing(
				Special.messagePoint("서쪽에 아이템이 놓여 있습니다. 하지만 조심하세요! 아무래도 함정이 설치된 것 같습니다. 당신은 \"s\" 키를 눌러 함정을 찾을 수 있습니다. 만약 당신이 함정 해체 기술을 가지고 있다면 \"a\" 키를 누른 뒤 함정 해체 기술을 선택해  그 함정을  해제할 수도 있습니다. 그것이 불가능하다면 위험을 무릅쓰고 그 위로 올라가 아이템을 얻을 수도 있겠지요....")
				,22,23
		);
		
		// tunnel end
		m.setTile(18,11,m.floor());
		m.addThing("잠긴 문",18,11);
		m.addThing(
				Special.messagePoint("몇몇 문은 잠겨있을 수도 있습니다. 당신이 알맞은 열쇠를 가지고 있거나 자물쇠따기 도구와 자물쇠따기 기술을 가지고 있을 경우 이 문을 열 수 있습니다. 그것도 불가능하다면 가장 좋은 방법은 \"k\"키를 눌러 문을 힘껏 걷어차는 것입니다.")
				,18,12
		);
		
		
		m.set("WanderingRate",0);
		m.replaceTiles(0,Tile.CAVEWALL);
		return m;
	}
	
	public static Map buildTutorialMap() {
		Map m=new Map(25,25);
		m.setTheme("village");
		m.set("설명","트레이드포스트 여관");
		m.set("레벨",1);
		
		// overall building structure
		Outdoors.buildOutdoors(m,0,0,24,24,Tile.GRASS);
		m.clearArea(0,0,18,24);
		m.fillArea(6,6,14,14,Tile.CAVEWALL);
		m.fillArea(7,7,13,13,Tile.CAVEFLOOR);
		m.fillArea(3,7,6,14,Tile.CAVEWALL);
		m.fillArea(4,8,5,13,Tile.CAVEFLOOR);
		m.setTile(10,14,Tile.CAVEFLOOR);
		m.addThing(Fire.create(4),10,14);
		
		// mini temple
		{
			int x=10;
			int y=1;
		
			m.fillArea(x,y,x+4,y+3,m.wall());
			m.fillArea(x+1,y+1,x+3,y+2,Tile.STONEFLOOR);
			m.setTile(x+2,y+3,Tile.STONEFLOOR);
			m.addThing("ornate door",x+2,y+3);
			m.addThing("stone altar",x+2,y+1);
			m.addThing(
					Special.messagePoint("북부 카라인의 사람들은 매우 종교적이며, 그 때문에 이 지역 곳곳에서 사당과 제단을 찾을 수 있을 것입니다. 당신은 언제나 \"_\"키를 눌러 신의 가호를 기도할 수 있습니다.")
					,x+2,y+2
			);
		}
		
		// well garden
		m.addThing("[IsWell]",8,2);
		for (int x=6; x<=10; x++) m.addThing("나무",x,0);
		m.addThing("나무",2,0);
		m.addThing("수풀",1,2);
		m.addThing("나무",0,3);
		m.addThing("나무",0,1);
		m.addThing("[IsWeapon]",4,0);
		
		//bottom trees
		m.addThing("나무",16,23);
		m.addThing("나무",14,23);
		m.addThing("나무",14,24);
		m.addThing("나무",12,24);
		
		// back garden
		m.setTile(0,7,Tile.RIVER);
		m.fillArea(0,8,2,9,Tile.RIVER);
		m.addThing(
				Special.messagePoint("당신이 수영 기술을 익히고 있다면 이 얕은 물은 쉽게 건너갈 수 있습니다. 그외에도, 당신은 배를 찾아 타고 건너갈 수도 있습니다.")
				,1,7
		);
		
		// herb garden
		for (int y=20; y<=23; y++) {
			for (int x=1; x<=5; x++) {
				if (RPG.d(2)==1) m.addThing(Lib.createType("IsHerb",RPG.d(6)),x,y);
			}
		}
		m.addThing(
				Special.messagePoint("풍족한 토양이 있는 곳에서는 약초를 찾을 수 있습니다. 여러 종류의 약초들은 그 마법적 특성 때문에 매우 애지중지됩니다. 약초 지식의 대가들은 그러한 약초들을 더욱 유용하게 활용할 수 있습니다. 몇몇 약초들은 위험할 수도 있으니, 먼저 어떠한 것인지를 정확히 알아두는 것이 좋습니다.")
				,3,22
		);
		
		// mini outhouse
		{
			int x=2;
			int y=1;
		
			m.fillArea(x,y,x+4,y+6,m.wall());
			m.fillArea(x+1,y+1,x+3,y+2,Tile.STONEFLOOR);
			m.fillArea(x+1,y+4,x+3,y+5,Tile.CAVEFLOOR);
			m.setTile(x+2,y+3,Tile.STONEFLOOR);
			m.setTile(x+4,y+4,Tile.CAVEFLOOR);
			m.setTile(x+0,y+4,Tile.CAVEFLOOR);
			m.addThing("튼튼한 문",x+2,y+3);
			m.addThing("튼튼한 문",x+4,y+4);
			m.addThing("쇠창살",x+0,y+4);
			Thing p=Lib.create("마을여성");
			AI.name(p,"부르샤");
			AI.setGuard(p,m,x+1,y+1);
			m.addThing(p,x+1,y+1);
			m.addThing(Lib.create("햄"),x+1,y+1).set("IsOwned",1);
			m.addThing(Fire.create(10),x+3,y+1);
			m.addThing("stone bench",x+3,y+2);
            p.set("OnChat", new BurthaTheTownsWoman());
		}
		
		// passageways
		m.fillArea(6,10,14,10,Tile.CAVEFLOOR);
		m.addThing(Lib.create("문"),14,10);
		m.addThing(
				Special.messagePoint("당신은 그 문으로 움직여서 자동으로 문을 열 수 있습니다. 또한 \"o\" 키를 눌러 문을 열거나 닫을 수도 있습니다.")
				,15,10
		);
		m.addThing(Lib.create("inn sign"),15,9);
		m.addThing(Lib.create("potted flower"),15,11);
		m.setTile(10,6,Tile.CAVEFLOOR);
		m.addThing(Lib.create("문"),10,6);
		
		
		
		// main room message points
		m.addThing(
				Special.messagePoint("당신은 여관의 사람들 주변에 서서 \"c\" 키를 누름으로서 그들과 대화를 나눌 수가 있습니다."
						+"당신이 여행중에 만나는 많은 이들은 당신에게 유용한 정보를 주거나 당신의 임무에 도움이 되는 것을 줄 수도 있습니다.")
				,13,10
		);
		
		m.addThing(
				Special.messagePoint("당신의 옆에 있는 문은 잠겨 있습니다. 당신은 이 문을 열 방법을 찾아야만 합니다. "
						+"던젼에서라면 \"k\"키를 눌러 잠긴 문을 부술 수도 있지만, 이 지역 사람들은 당신이 자기 눈 앞에서 그러는 것을 그다지 좋아하지 않을 것입니다!")
				,7,10
		);
		
		// stable area
		m.fillBorder(7,14,18,22,Tile.CAVEWALL); // wall
		m.fillArea(8,15,9,21,Tile.CAVEFLOOR); // stable floor
		m.fillBorder(7,14,10,22,Tile.CAVEWALL); // stable wall
		m.fillArea(15,14,16,14,Tile.GRASS);// entrance
		m.setTile(10,14,Tile.CAVEFLOOR);
		m.setTile(10,16,Tile.CAVEFLOOR);
		m.fillArea(9,15,11,15,Tile.CAVEWALL);
		m.addThing(Lib.create("튼튼한 문"),10,16);
		m.addThing(
				Special.messagePoint("The stables here are filled with the smell of fresh manure. You spy a ladder going upstairs to some kind of loft. There is also a crude knife on the floor, that seems to have been discarded.")
				,10,16
		);
		m.addThing(Lib.create("돌 단도"),8,17);
		m.addThing(
				Special.messagePoint("You can pick up and use this knife as a weapon. Press \",\" (comma) or \"p\" to pick it up. Then press \"w\" to wield it as a weapon.")
				,8,17
		);
		{
			Thing t=Lib.create("튜토리얼 다락방");
			m.addThing(t,8,15);
		}
		m.addThing(
				Special.messagePoint("이 사다리를 타려면 \"x\" 키를 누르세요.")
				,8,15
		);
		m.fillArea(7,18,10,18,Tile.CAVEWALL);
		m.setTile(10,20,Tile.CAVEFLOOR);
		m.addThing(Lib.create("숨겨진 문"),7,19);
		m.addThing(Lib.create("튼튼한 문"),10,20);
		Thing p=Lib.create("농부");
		AI.name(p,"로치");
		AI.setGuard(p,m,13,18,17,22);
		m.addThing(p,15,19);
        m.addThing(
            Special.messagePoint("There is Rotchy the farmer to the south. " +
            "You can go to him and chat by pressing \"c\"."),16,14);
        p.set("OnChat",new RotchyTheFarmer());

		m.addBlockingThing(Lib.create("[IsBarrel]"),13,18,17,22);
		m.addBlockingThing(Lib.create("[IsBarrel]"),13,18,17,22);
		m.addBlockingThing(Lib.create("[IsBarrel]"),13,18,17,22);
	
		// cellar stairs
		m.setTile(13,15,Tile.CAVEWALL);
		{
			Thing t=Lib.create("튜토리얼 지하실");
			m.addThing(t,12,15);
		}
		m.addThing(
				Special.messagePoint("You see some stairs here heading down into a dark cellar. You can hear the sounds of rats scuttling below. Move onto the stairs and press \"x\" if you want to venture into the dark cellar.")
				,12,16
		);
		
		
		// storeroom
		m.addThing(Lib.create("잠긴 문"),6,10);
		m.addThing(Lib.create("fish"),4,8);
		m.addThing(Lib.create("salmon"),5,8);
		m.addThing(Lib.create("[IsBarrel]"),4,13);
		m.addThing(Lib.create("[IsBarrel]"),5,13);
		m.setTile(4,7,Tile.CAVEFLOOR);
		m.addThing("잠긴 문",4,7);
		m.fillArea(2,9,4,9,Tile.RIVER);
		m.addThing("파괴불가능한 쇠창살",3,9);

		
		// entrance
		m.setEntrance(Portal.create("invisible portal"));
		m.addThing(m.getEntrance(),m.width-2,10);
		
		// pathway
		int treegap=RPG.d(3);
		String tree=RPG.pick(new String[] {"나무","소나무","커다란 나무","수풀"});
		for (int x=18; x<m.width; x+=treegap) {
			m.addThing(tree,x,8);
			m.addThing(tree,x,12);
		}
		
		m.fillArea(15,10,m.width-1,10,Tile.STONEFLOOR);
		
		// map settings
		m.set("WanderingRate",0);
		m.set("EnterMessageFirst",
			"jRogue에 오신걸 환영합니다!\n"+	
			"트레이드포스트 여관은 왼쪽에 서 있습니다. 친절한 지역민들이 이 세계에 대한 소개를 해 주기를 꺼리지 않는 곳이죠. "
			+" 만약 당신이 이미 숙련된 모험가라면, 이 지역을 떠나 더 큰 모험을 찾아 떠날 수도 있습니다.\n"
			+"그럼 jRogue를 즐겨주시길 바랍니다!"
		);
		addPeople(m);
		
		return m;
	}

    private static boolean isBusy(
            final double p, final int ch, final int chToTest) {
        if (!RPG.p(p))
            return false;
        if (RPG.test(ch, chToTest))
            return false;
        final int chPolite = (int) (0.8*chToTest);
        String[] busy;
        if (RPG.test(ch, chPolite)) {
            busy = new String[] {
                //-More polite answer
                "미안하오, 난 지금 좀 바쁘다오. 나중에 다시 오겠소?",
                "지금은 좀 바쁘오, 미안하오. 나중에 다시 오시오.",
                "미안하네, 지금 좀 바쁘군. 나중에 다시 오게나.",
                "미안하네, 난 지금 바쁘다네. 나중에 오게, 알겠나?",
            };
        } else {
            busy = new String[] {
                "지금 좀 바쁘군, 나중에 오게.",
                "지금은 좀 바쁘군, 나중에 다시 들르게.",
                "지금은 바쁘다네, 나중에 다시 오게.",
                "지금은 좀 바쁘다네, 나중에 다시 오게. 알겠나?",
            };
        }
        Game.quotedMessage(RPG.pick(busy));
        return true;
    }



    private static void sayName(Thing t) {
        Game.message("당신은 " + t.getTheName()+"에게 말을 겁니다.");
    }

    private static boolean isExoticRace(final String race) {
        return !race.equals("인간") && !race.equals("호빗");
    }
    /**
     * Some races are considered as "unpleasant". We take this in account while
     * talking to such Hero.
     */
    private static boolean isUnpleasantRace(final String race) {
        if (race.equals("하프 오크"))
            return true;
        if (race.equals("하프 트롤"))
            return true;
        return false;
    }

    /**
     * @param h  Hero
     * @return true when hello has been said; false otherwise
     */
    private static boolean sayHello(final Thing h, final double p1,
            final double p2, final double p3) {
        final String race = h.getString("종족");
        if (!RPG.p(p1))
            return false;
        if (isUnpleasantRace(race) &&
                RPG.p(p2) &&
                !RPG.test(h.getStat("CH"),3)) {
            final String[] part1 = {
                    "오, 당신은 ",
                    "그렇군, 당신은 "
            };
            final String part2 = "로군. ...사실 말하자면 이 마을 사람들은 당신네 종족을 그다지 좋아하지 않소. ";
            final String[] part3 = {
                    "하지만 어쨌건, 환영하오.",
                    "어쨌건, 환영하오.",
                    "어쨌건, 안녕하시오.",
                    "어쨌건, 안녕하신가요."
            };
            Game.quotedMessage(RPG.pick(part1) + race + part2 + RPG.pick(part3));
            return true;
        }//if

        if (isExoticRace(race)) {
            if (RPG.p(p2)) {
                final String[] part1 = {
                    "오, 당신은 ",
                    "아, 당신은 ",
                    "그렇군요, 당신은 "
                };
                final String[] part2 = {
                    "로군. ...당신 종족은 한번도 이곳에 방문한 적이 없었는데. ",
                    "로군. ...당신네 종족은 여긴 거의 보이지 않았소. ",
                    "로군. ...당신네 종족은 이전에 한 번도 본 적이 없었습니다. "
                };
                final String[] part3 = {
                    "아무튼, 안녕.",
                    "아무튼, 안녕!",
                    "아무튼, 안녕하세요.",
                    "아무튼, 안녕하세요!",
                    "아무튼, 안녕하신가요.",
                    "아무튼, 어서오세요!"
                };
                Game.quotedMessage(RPG.pick(part1) + Text.krSub(race, "이름") + RPG.pick(part2) + RPG.pick(part3));
                return true;
            }
            if (RPG.p(p3)) {
                final String[] begin = {
                    "안녕, ",
                    "안녕하세요, ",
                    "어서오세요, ",
                    "반가와요, "
                };
                Game.quotedMessage(RPG.pick(begin) + race + ".");
                return true;
            }
        }//if race is "exotic"
        final String[] hello = {
            "안녕.",
            "안녕!",
            "안녕하신가요.",
            "안녕하세요.",
            "안녕하세요!",
            "반가와요.",
            "어서와요!",
            "안녕, 친구.",
            "만나게 되어서 기쁘네요.",
            "안녕, 같은 여행자를 만나게 되어서 기쁘군요.",
            "안녕하세요. 당신도 저 같은 여행자인 듯 하네요."
        };
        Game.quotedMessage(RPG.pick(hello));
        return true;
    }

    private static void addPeople(Map m) {
		Thing t;
		
		t=Lib.create("대장장이");
		AI.name(t,"여관주인 실라스");
		AI.setGuard(t,m,6,7,8,9);
		m.addThing(Lib.create("남북방향 테이블"),8,7);
		m.addThing(Lib.create("남북방향 테이블"),8,8);
		m.addThing(Lib.create("남북방향 테이블"),8,9);
		m.addThing(Lib.create("원형의자"),9,7);
		m.addThing(Lib.create("원형의자"),9,9);
		m.addThing(Lib.create("햄"),8,7);
        final SilasInnkeeper silas = new SilasInnkeeper();
		t.set("OnChat",silas);
		m.addThing(t,7,8);


		
		t=Lib.create("경비병");
		AI.name(t, "로스코 버얼");
		AI.setGuard(t,m,12,8,12,8);
		m.addThing(t,12,8);
		m.addThing(Lib.create("원형의자"),12,8);
		m.addThing(Lib.create("원형의자"),11,7);
		m.addThing(Lib.create("테이블"),11,8);
        final RoscoBurrl rosco = new RoscoBurrl();
		t.set("OnChat", rosco);
		// girl
		t=Lib.create("시골 처녀");
		AI.setGuard(t,m,9,8,9,8);
		m.addThing(t,9,8);
		
		// teacher
		t=Lib.create("교사");
		AI.setGuard(t,m,12,13,12,13);
		m.addThing(t,12,13);
		m.addThing(Lib.create("테이블"),11,13);
		m.addThing(
				Special.messagePoint("당신의 옆에 서 있는 로브를 입은 신사는 정식교육을 받은 교사입니다."
						+" 당신이 충분한 경험을 이미 얻었다면 그에게 교육을 받아 기술을 더 향상시킬 수가 있습니다."
						+" 만약 당신이 \"c\" 키를 눌러 그와 대화를 하면 그는 자신이 당신에게 기술을 알려줄 수 있는지" 
						+" 말해 줄 것입니다. 당신은 \"v\" 키를 눌러 자신의 현재 기술과 기타 유용한 정보들을 볼 수"
						+" 있습니다.")
				,12,12
		);
		
		// Miira the ranger
		t=Lib.create("순찰자");
		t.set("대화횟수",0);
		AI.name(t,"미라");
		AI.setGuard(t,m,11,7,11,7);
		m.addThing(t,11,7);
        final MiiraTheRanger miira = new MiiraTheRanger();
		t.set("OnChat", miira);

        //-Object ssilas, miira and rosco contain several cross-rererences:
        silas.setMiira(miira);
        miira.setSilas(silas);
        miira.setRosco(rosco);
        rosco.setMiira(miira);

	}
	
	public static void init() {
		Thing t;
		
		t=Lib.extend("여관 다락층 열쇠","금속 열쇠");
		t.set("빈도",0);
		Lib.add(t);
		
	}
}
